magiclanternfandomcom-20200223-history
Magic Lantern API
In this page I'm trying to understand the Magic Lantern structure and document its API. Related: Extending Magic Lantern API docs generated by Doxygen: *for 5D: http://a1ex.bitbucket.org/ML/5D/index.html *for 550D: http://a1ex.bitbucket.org/ML/550D/index.html Alex =5d-hack.c= It seems that 5d-hack.c also works on the 550D, so renaming it might remove a tiny amount of confusion. =audio.h and audio.c= int16_t audio_read_level(int channel) Read the raw level from the audio device. Expected values are signed 16-bit? * channel: 0 (left) or 1 (right) How it works: reads the value from 0xC0920000 + 0x110. uint8_t audio_ic_read(unsigned cmd) void audio_ic_write(unsigned cmd) Read and write commands to the AK4646. These two functions are wrappers to DryOS APIs _audio_ic_read and _audio_ic_write. Datasheet for the AK4646 audio chip is here: Datasheets According to this post, both 550D and 5D use the AK4646 chip, or a compatible one. I believe the first two bytes (MSB) of cmd are the address of the audio registers, and the last two bytes are the value written there. Audio registers: #define AUDIO_IC_PM1 0x2000 #define AUDIO_IC_PM2 0x2100 #define AUDIO_IC_SIG1 0x2200 #define AUDIO_IC_SIG2 0x2300 #define AUDIO_IC_ALC1 0x2700 #define AUDIO_IC_ALC2 0x2800 #define AUDIO_IC_IVL 0x2900 #define AUDIO_IC_IVR 0x2C00 #define AUDIO_IC_OVL 0x2A00 #define AUDIO_IC_OVR 0x3500 #define AUDIO_IC_ALCVOL 0x2D00 #define AUDIO_IC_MODE3 0x2E00 #define AUDIO_IC_MODE4 0x2F00 #define AUDIO_IC_PM3 0x3000 #define AUDIO_IC_FIL1 0x3100 #define AUDIO_IC_HPF0 0x3C00 #define AUDIO_IC_HPF1 0x3D00 #define AUDIO_IC_HPF2 0x3E00 #define AUDIO_IC_HPF3 0x3F00 #define AUDIO_IC_LPF0 0x6C00 #define AUDIO_IC_LPF1 0x6D00 #define AUDIO_IC_LPF2 0x6E00 #define AUDIO_IC_LPF3 0x6F00 Sample code from audio.c: ./audio.c:515: audio_ic_write( AUDIO_IC_PM1 | 0x6D ); // power up ADC and DAC ./audio.c:527: audio_ic_write( AUDIO_IC_PM3 | 0x00 ); // internal mic ./audio.c:529: audio_ic_write( AUDIO_IC_PM3 | 0x07 ); // external input ./audio.c:532: audio_ic_write( AUDIO_IC_ALC1 | gain.alc1 ); // disable all ALC void audio_ic_set_input_volume(int channel, int gain) * channel: 0 or 1 * gain: in DB. ./audio.c:537: audio_ic_set_input_volume( 0, dgain_r ); ./audio.c:538: audio_ic_set_input_volume( 1, dgain_l ); dgain_r and dgain_l are audio.dgain.r and audio.dgain.l from magic.cfg (0 by default). This is defined in audio.c. To use it, you have to declare it in audio.h. void audio_ic_set_mgain(unsigned bits) /** Write the MGAIN2-0 bits. * Table 19 for the gain values: * * 0 +0 dB * 1 +20 dB * 2 +26 dB * 3 +32 dB * 4 +10 dB * 5 +17 dB * 6 +23 dB * 7 +29 dB * * Why is it split between two registers? I don't know. */ mgain is audio.mgain from magic.cfg, and the default value is 4 (i.e. 10 dB). This is defined in audio.c. To use it, you have to declare it in audio.h. What is mgain? Some kind of master gain, for both channels? =bmp.h and bmp.c= void bmp_printf(fontspec, x, y, const char * fmt, ...) This is printf at (x,y) with a given font. *fontspec: FONT_HUGE, FONT_LARGE, FONT_MED or FONT_SMALL. You can include color info, too. *x and y: coordinates of the text, in pixels, unsigned. (0,0) is on the upper left corner. *fmt: the same like printf. Handles newlines. To print in colors, use the FONT macro, defined in bmp.h: FONT(font,fg,bg) Color example from AJ: bmp_printf( FONT(FONT_SMALL,COLOR_RED,COLOR_BG), 000, g_bmp_height-16, "AJ: XYC range. x=%d y=%d c=%d ",x,y,colour); List of colors (bmp.h): /** Some selected colors */ #define COLOR_EMPTY 0x00 // total transparent #define COLOR_BG 0x14 // transparent gray #define COLOR_BG_DARK 0x03 // transparent black #define COLOR_WHITE 0x01 // Normal white #define COLOR_BLUE 0x0B // normal blue #define COLOR_RED 0x08 // normal red #define COLOR_YELLOW 0x0F // normal yellow uint8_t * bmp_vram(void) Returns Bitmap overlay VRAM address (bvram). * Pixel format: 8-bit fixed palette (see VRAM and Cropmarks). * Size: bmp_width() x bmp_height() pixels (720x480). * Pitch (size of a scanline in memory): pitch = bmp_pitch() => 960 * Addressing mode (how to get the address of a pixel): first_row = bvram + y * pitch + x; void bmp_fill(color, x, y, w, h); *color: uint8_t *x,y,w,h: uint32_t (these numbers describe a rectangle) * Fill a section of bitmap memory with solid color. Only has a four-pixel resolution in X. * Is there a color palette? Yes! (see the VRAM and Cropmarks pages) struct bmp_file_t* bmp_load(const char * name); Load a BMP file into memory so that it can be drawn on screen. Used for cropmarks. * How to draw it on screen? Pixel by pixel, on the BMP overlay. The code is in zebra.c. =property.h and property.c= void prop_request_change(unsigned property, void* addr, size_t len) Change a property. This is a DryOS call. * property: an ID from the List of Properties (they are declared in property.h) * addr: pointer to the new property value * len: size of the value located at addr * What data type do properties have? I believe most of them are integers or strings. The list of properties do not specify the data type. Example code from lens.h: static inline void lens_set_aperture(unsigned aperture) { prop_request_change( PROP_APERTURE, &aperture, sizeof(aperture) ); } #define PROP_HANDLER(id) Use this to get notified when a property changes. This macro allows you to declare a function which is called automatically (something like interrupts). * id: an ID from the List of Properties (they are declared in property.h) Example code from lens.c: PROP_HANDLER( PROP_ISO ) { const uint32_t raw = *(uint32_t *) buf; lens_info.raw_iso = raw; lens_info.iso = raw/2 < COUNT(iso_values) ? iso_values[ raw / 2 ] : 0; return prop_cleanup( token, property ); } void prop_get_value(unsigned property, void * addr, size_t * len); Parameters: same as prop_request_change. This is a DryOS call, only identified in 5D2/1.1.0. Not sure if it works in 550D. todo: Does initial value of len matter? =lens.c and lens.h= Control ISO, shutter, aperture and stuff like that. Semaphores lens_sem = create_named_semaphore( "lens_info", 1 ); focus_done_sem = create_named_semaphore( "focus_sem", 1 ); job_sem = create_named_semaphore( "job", 1 ); Functions void lens_set_aperture(unsigned aperture) *aperture: see lens.h for possible values. There are macros like APERTURE_1_8, APERTURE_4_0 and so on. void lens_set_iso(unsigned iso) *iso: see lens.h for possible values. There are macros from ISO_100 to ISO_12500. void lens_set_shutter(unsigned shutter) *shutter: see lens.h for possible values. There are macros from SHUTTER_30 to SHUTTER_4000. void lens_set_ae(int cmd) Exposure compensation? *cmd: it seems to be the desired exposure, in EV, or 1/3 EV, or something like this. Not sure. int lens_get_ae(void) // This is currently broken. Returns 0. int lens_take_picture(int wait) Takes a picture. *wait: number of milliseconds to wait (this is a timeout) Internally, this function calls: call( "Release" ); and does a bit of black magic with some semaphores. uint16_t bswap16(uint16_t val) bswap16(0xABCD) => 0xCDAB =menu.h and menu.c= See How to create a menu =ptp.h and ptp.c= These files contain macros and functions for extending PTP capabilities of the camera. Until I understand how this works, see the PTP page. It would be nice to create some Python wrappers for these capabilities. See Remote_control_with_PTP_and_Python. I'll try to create some Python bindings for Mweerden's patched libptp/ptpcam. Also, I'd like to be able to upload files on the camera via PTP and to poke/peek memory locations. CHDK does this afaik. =tasks.h= #define INIT_FUNC(NAME, ENTRY) Define an initialization function, which is executed at firmware startup (I think so). *NAME: a string, used in debug messages *ENTRY: pointer to a function with this signature: static void functionname(void) These init functions are called here: *5d-hack.c my_init_task -> menu_init -> call_init_funcs #define TASK_CREATE(NAME, ENTRY, ARG, PRIORITY, FLAGS) Creates a task which runs in parallel with the Canon firmware. Each feature in ML seems to have its own task: focus_task, bracket_task, dump_task, zebra_task, menu_task and so on. *NAME: a string, used in debug messages. *ENTRY: pointer to a function with this signature: static void functionname(void) *ARG: it seems unused, and always 0. *PRIORITY: Task priority. Values from ML code: 0x10, 0x18, 0x1e, 0x1f. I don't know whether higher values mean higher priority or viceversa. 0x1F = 31 is the lowest prioriity. Example task priorities http://magiclantern.wikia.com/wiki/2.0.4_Tasks *FLAGS: 0x1000 (I don't know what that means) The tasks are started in 5d-hack.c, in my_init_task, AFTER call_init_funcs, with several calls to task_create, which is a function from the Canon code. #define TASK_OVERRIDE(orig_func, replace_func) This REPLACES a Canon task with some custom function from Magic Lantern. I don't understand how it does that, but it works!!! $ grep -nr "TASK_OVERRIDE" ./ ./tasks.h:107:#define TASK_OVERRIDE( orig_func, replace_func ) \ ./hotplug.c:68:TASK_OVERRIDE( hotplug_task, my_hotplug_task ); ./gui.c:221:TASK_OVERRIDE( gui_main_task, my_gui_main_task ); ./audio.c:876:TASK_OVERRIDE( sounddev_task, my_sounddev_task ); ./audio.c:977:TASK_OVERRIDE( audio_level_task, my_audio_level_task );